package bliVideo

/**
 * 37-Kotlin的可空性 https://www.bilibili.com/video/BV1wf4y1s7TG/?p=37
 * 在Java中我们司空见惯的空指针异常NullPointerException，带给了我们很多麻烦。
 * Kotlin作为更强大的语言，势必会基于以往的语言设计经验对其进行改良。
 * Kotlin更多地把运行时可能会出现的null问题，以编译时错误的方式，提前在编译期强迫我们重视起来，
 * 而不是等到运行时报错，防范于未然，提高了我们程序的健壮性。
 *
 * 对于null值问题，Kotlin反其道而行之，除非另有规定，否则变量不可为null值，这样一来，运行时崩溃从根源上得到解决。
 *
 *
 */
fun main41() {
    var str = "Test"
    /**
     * 为了避免NullPointerException, Kotlin的做法是不让我们给非空类型变量赋null值, 但null在Kotlin中依然存在。
     */
//    str = null                //Null can not be a value of a non-null type String

    var str2: String? = "Test"  //可空类型
    str2 = null
    println(str2)


    //38-安全调用操作符
    var str3: String? = "Test"          //可空类型
    val capitalize = str3?.capitalize() //首字母大写
    val length = capitalize?.length
    println("capitalize = $capitalize, length = $length")
}


/**
 * 39-使用带let的安全调用
 * 安全调用允许在可空类型上调用函数，但是如果还想做点额外的事，
 * 比如创建新值, 或判断不为null就调用其他函数，怎么办? 可以使用带let函数的安全调用操作符。
 * 你可以在任何类型上调用let函数，它的主要作用是让你在指定的作用域内定义一个或多个变量。
 */
fun main42() {
    var str: String? = null     //null
    str = ""                    //str = "", 或由空格组成!
    str = "butterfly"           //Butterfly9

    /**
     * 重新赋值, 否则 let 里面的操作不会影响 str 的值!!!
     */
    str = str?.let {
        if (it.isNotBlank()) {      //it = "", 或由空格组成!
            it.capitalize() + it.length
        } else {
            "str = \"\", 或由空格组成!"
        }
    }
    println(str)
}


/**
 * 40-非空断言操作符
 * !!.  又称感叹号操作符，当变量值为null是，会抛出KotlinNullPointerException。
 */
fun main43() {
    var str: String? = null
    str = str!!.capitalize()
    println(str)


    /**
     * 41-对比使用if判断null值情况
     */
    var str2: String? = null
//    str2 = str2.capitalize()      //Java 一样的都是1句代码
    println(str2)
}


/**
 * 42-空合并操作符
 * ?:  操作符的意思是，如果左边的求值结果为null，就使用右边的结果值。
 */
fun main44() {
    var str1: String? = null
    val str3 = str1 ?: "butterfly 3"
    println(str3)

    //空合并操作符也可以和let函数一起使用来代替if/else语句。
    str1 = str1?.let { it.capitalize() } ?: "butterfly 4"
    println(str1)

    str1 = null
    str1 = str1?.capitalize() ?: "butterfly 5"
    println(str1)
}
